package cn.thoughtworks.school.services;

import cn.thoughtworks.school.entities.SubjectiveQuiz;
import cn.thoughtworks.school.entities.User;
import cn.thoughtworks.school.entities.dto.AssignmentQuizData;
import cn.thoughtworks.school.repositories.SubjectiveQuizRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SubjectiveQuizService {

  @Autowired
  private SubjectiveQuizRepository subjectiveQuizRepository;
  @Autowired
  private Utils utils;
  @Value("${subjective-type}")
  private String type;
  @Autowired
  private UserCenterService userCenterService;
  @Autowired
  private QuizService quizService;

  public SubjectiveQuiz createSubjectiveQuiz(Map data, User current) {
    Long organizationId = userCenterService.getUserCurrentOrganizationId(current.getId());
    SubjectiveQuiz quiz = buildSubjective(data, organizationId, current);

    SubjectiveQuiz newSubjectiveQuiz = subjectiveQuizRepository.save(quiz);

    return newSubjectiveQuiz;
  }

  private SubjectiveQuiz buildSubjective(Map data, Long organizationId, User current) {
    SubjectiveQuiz quiz = new SubjectiveQuiz();
    quiz.setMakerId(current.getId());
    quiz.setOrganizationId(organizationId);
    quiz.setReferenceNumber(0L);
    quiz.setIsAvailable(true);
    quiz.setDescription((String) data.get("description"));
    quiz.setTags(utils.formatTags((List<String>) data.get("tags"), current.getId()));
    quiz.setRemark((String) data.get("remark"));
    quiz.setCreateTime(new SimpleDateFormat("YYYY-MM-dd HH-mm-ss").format(new Date()));
    quiz.setReferenceAnswer((String) data.get("referenceAnswer"));
    quiz.getTags().stream().forEach(tag -> tag.setOrganizationId(organizationId));
    return quiz;
  }

  public Page<SubjectiveQuiz> getSubjectiveQuizzesPageable(Pageable pageable, Long id, Long userId, String description, List<String> tags, User user) {
    Long organizationId = userCenterService.getUserCurrentOrganizationId(user.getId());
    List<Long> quizIds = getQuizIdsByTags(tags);
    Page<SubjectiveQuiz> subjectiveQuizPage = getSubjectiveQuizPage(organizationId, pageable, id, userId, description, quizIds);

    return  utils.format(subjectiveQuizPage, pageable);

  }

  private Page<SubjectiveQuiz> getSubjectiveQuizPage(Long organizationId, Pageable pageable, Long id, Long userId, String description, List<Long> quizIds) {
    return subjectiveQuizRepository.findAll((Specification<SubjectiveQuiz>) (root, query, criteriaBuilder) -> {
      List<Predicate> defaultPredicates = quizService.getDefaultPredicates(organizationId, id, userId, description, quizIds, root, criteriaBuilder);
      return criteriaBuilder.and(defaultPredicates.toArray(new Predicate[defaultPredicates.size()]));
      }, pageable);
  }

  private List<Long> getQuizIdsByTags(List<String> tags) {
    List<SubjectiveQuiz> quizzes = subjectiveQuizRepository.findSubjectivesByTags(tags);
    if (Objects.nonNull(tags) && quizzes.isEmpty()) {
      return Arrays.asList(-1L);
    }
    return quizzes.stream().map(SubjectiveQuiz::getId).collect(Collectors.toList());
  }

  public List<AssignmentQuizData> copy(List<AssignmentQuizData> subjectiveQuizzesData) {
    List<Long> ids = subjectiveQuizzesData.stream().map(AssignmentQuizData::getQuizId).collect(Collectors.toList());
    List<SubjectiveQuiz> subjectiveQuizzes = subjectiveQuizRepository.findByIdIn(ids);

    subjectiveQuizzesData.forEach(quizData -> {
      Long creatorId = quizData.getCreatorId();
      SubjectiveQuiz subjectiveQuiz = subjectiveQuizzes.stream()
        .filter(quiz -> quiz.getId().equals(quizData.getQuizId()))
        .findFirst().get();
      subjectiveQuiz.setTags(quizService.copyTags(quizData.getOrganizationId(),subjectiveQuiz.getTags(),creatorId));
      subjectiveQuiz = SubjectiveQuiz.copy(subjectiveQuiz, creatorId, quizData.getOrganizationId());
      subjectiveQuizRepository.save(subjectiveQuiz);
      quizData.setNewQuizId(subjectiveQuiz.getId());
    });
    return subjectiveQuizzesData;
  }

}
